/*
 *   Copyright (C) 2012  Jens Kieselbach
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You may obtain a copy of the License at http://www.gnu.org/licenses/gpl.html
 */

package de.kieselbach.javafx

import javafx.scene.image.Image
import javafx.scene.control.Separator
import javafx.geometry.Orientation
import javafx.scene.control.Button
import javafx.scene.control.Tooltip
import javafx.scene.image.ImageView
import javafx.scene.control.Menu
import javafx.scene.control.MenuItem
import javafx.scene.control.MenuBar
import javafx.scene.control.ToolBar
import javafx.scene.control.SeparatorMenuItem
import javafx.scene.input.KeyCombination
import javafx.scene.control.ContentDisplay

class UIResources {

    def resourceBundles = [:]
    def images = [:]

    def menubars = [:]
    def toolbars = [:]

    UIResources(def input) {

        def result = new XmlParser().parse(input)

        result.'resource-bundles'.'resource-bundle'.each() {elem ->
            def name = elem.'@name'
            def uri = elem.text()

            if (name != null && name.size() > 0 && uri != null && uri.size() > 0) {
                resourceBundles[name] = ResourceBundle.getBundle(uri)
            }
        }

        result.'images'.'image'.each() {elem ->
            def name = elem.'@name'
            def uri = elem.text()

            if (name != null && name.size() > 0 && uri != null && uri.size() > 0) {
                images[name] = new Image(getClass().getResourceAsStream(uri))
            }
        }

        result.'menu-bar'.each() {elem ->
            def set = elem.'@set'
            if(set != null) {
                set = set.trim()
                if(set.length() <= 0) {
                    set = null
                }
            }
            if(set == null) {
                set = 'default'
            }

            if(menubars[set] != null) {
                throw new IllegalArgumentException('A menu bar in set \'' + set + '\' is already defined!')
            }

            menubars[set] = elem
        }

        result.'tool-bar'.each() {elem ->
            def set = elem.'@set'
            if(set != null) {
                set = set.trim()
                if(set.length() <= 0) {
                    set = null
                }
            }
            if(set == null) {
                set = 'default'
            }

            if(toolbars[set] != null) {
                throw new IllegalArgumentException('A tool bar in set \'' + set + '\' is already defined!')
            }

            toolbars[set] = elem
        }
    }

    void buildToolBar(def uiset, def elements) {

        elements.each {elem ->
            if (elem.name() == 'button') {
                addButton(uiset, elem)
            }
            else if (elem.name() == 'separator') {
                uiset.toolBar.items.addAll(new Separator(Orientation.VERTICAL))
            }
        }
    }

    void addButton(def uiset, def elem) {
        def bundle = elem.'@resource-bundle'
        def key = elem.'@resource-key'
        def tooltip = elem.'@tooltip-key'
        def image = elem.'@image'
        def contentdisplay = elem.'@content-display'

        if ((bundle != null && bundle.size() > 0 && key != null && key.size() > 0) || (image != null && image.size() > 0)) {

            def button = new Button()
            button.id = 'toolbar-button'
            uiset.toolBar.items.addAll(button)

            if(contentdisplay == 'top') {
                button.contentDisplay = ContentDisplay.TOP
            }
            else if(contentdisplay == 'left') {
                button.contentDisplay = ContentDisplay.LEFT
            }
            else if(contentdisplay == 'bottom') {
                button.contentDisplay = ContentDisplay.BOTTOM
            }
            else if(contentdisplay == 'right') {
                button.contentDisplay = ContentDisplay.RIGHT
            }
            else {
                button.contentDisplay = ContentDisplay.CENTER
            }

            if (bundle != null && bundle.size() > 0) {
                if(key != null && key.size() > 0) {
                    button.text = resourceBundles[bundle].getString(key)
                }

                if(tooltip != null && tooltip.size() > 0) {
                    button.tooltip = new Tooltip(resourceBundles[bundle].getString(tooltip))
                }
            }

            if (image != null && image.size() > 0) {
                button.graphic = new ImageView(images[image])
            }

            def command = elem.text()
            if (command != null && command.size() > 0) {
                button.onAction = uiset
                uiset.targets[button] = command

                def resource = uiset.resources[command]
                if (resource == null) {
                    resource = new UIResource()
                    uiset.resources[command] = resource
                }

                resource.elements << button
            }
        }
    }

    void buildMenuBar(def uiset, def parent, def elements) {

        elements.each {elem ->
            if (elem.name() == 'menu') {
                addMenu(uiset, parent, elem)
            }
            else if (elem.name() == 'menu-item') {
                addMenuItem(uiset, parent, elem)
            }
            else if (elem.name() == 'separator') {
                addMenuSeparator(parent)
            }
        }
    }

    def initMenu(def menu, def text, def image) {
        menu.text = text

        if (image != null && image.size() > 0) {
            menu.graphic = new ImageView(images[image])
        }

        return menu
    }

    void addMenu(def uiset, def parent, def elem) {
        def bundle = elem.'@resource-bundle'
        def key = elem.'@resource-key'
        if (bundle != null && bundle.size() > 0 && key != null && key.size() > 0) {

            def text = resourceBundles[bundle].getString(key);
            def Menu menu = new Menu(text)

            if(parent instanceof MenuBar) {
                parent.menus.addAll(initMenu(menu, text, elem.'@image'))
            }
            else {
                parent.items.addAll(initMenu(menu, text, elem.'@image'))
            }
            if (elem.'*'.size() > 0) {
                buildMenuBar(uiset, menu, elem.'*')
            }
        }
    }

    void addMenuItem(def uiset, def parent, def elem) {
        def bundle = elem.'@resource-bundle'
        def key = elem.'@resource-key'
        if (bundle != null && bundle.size() > 0 && key != null && key.size() > 0) {
            def text = resourceBundles[bundle].getString(key)
            def MenuItem menuitem = new MenuItem()

            if(parent instanceof MenuBar) {
                parent.menus.addAll(initMenu(menuitem, text, elem.'@image'))
            }
            else {
                parent.items.addAll(initMenu(menuitem, text, elem.'@image'))
            }

            def accel = elem.'@accelerator'
            if (accel != null) {
                menuitem.accelerator = KeyCombination.keyCombination(accel)
            }

            def command = elem.text()
            if (command != null && command.size() > 0) {
                menuitem.onAction = uiset
                uiset.targets[menuitem] = command

                def resource = uiset.resources[command]
                if (resource == null) {
                    resource = new UIResource()
                    uiset.resources[command] = resource
                }

                resource.elements << menuitem
            }
        }
    }

    void addMenuSeparator(def parent) {

        if(parent instanceof MenuBar) {
            parent.menus.addAll(new SeparatorMenuItem())
        }
        else {
            parent.items.addAll(new SeparatorMenuItem())
        }
    }

    // -------------------------------------------------------------

    UISet createUISet(def set) {

        if(set != null) {
            set = set.trim()
            if(set.length() <= 0) {
                set = null
            }
        }
        if(set == null) {
            set = 'default'
        }

        def uiset = new UISet()

        def menubar = menubars[set]
        if(menubar != null) {
            uiset.menuBar = new MenuBar()

            if (menubar.'*'.size() > 0) {
                buildMenuBar(uiset, uiset.menuBar, menubar.'*')
            }
        }

        def toolbar = toolbars[set]
        if(toolbar != null) {
            uiset.toolBar = new ToolBar()

            if (toolbar.'*'.size() > 0) {
                buildToolBar(uiset, toolbar.'*')
            }
        }

        uiset
    }
}
